package com.example.demo.controller;


import com.example.demo.model.LogInfo;
import com.example.demo.model.UserInfo;
import com.example.demo.service.LogInfoService;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    // 数据事务管理器
    @Resource
    private DataSourceTransactionManager transactionManager;

    // 事务的定义
    private TransactionDefinition transactionDefinition;


//    1.编程事务
    @RequestMapping("/adduser")
    public int addUser(UserInfo userInfo) {
        // 运行之前 我们要判断传入的参数是否为空 如果为空 会导致sql拼接错误
        if (userInfo == null ||
                !StringUtils.hasLength(userInfo.getUsername()) ||
                !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }
        // 开启事务
        // 该方法有返回值 我们通过该值来提交 或者 回滚事务
        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
        int ret = userService.addUser(userInfo);
        System.out.println("adduser 受影响行数" + ret);
        // 提交事务或者回滚事务
        //回滚事务
        transactionManager.rollback(transactionStatus);
        //提交事务
//        transactionManager.commit(transactionStatus);

        return ret;
    }



//    2.声明事务  加上注解    @Transactional
    @RequestMapping("/adduser2")
    @Transactional(timeout = -1) //设置方法执行时间默认是-1 就是没有限制
    // 如果设置了3 那么如果我们运行时间超过3那么就会发生事务回滚  在UserService中设置
    public int addUser2(UserInfo userInfo) {
        // 运行之前 我们要判断传入的参数是否为空 如果为空 会导致sql拼接错误
        if (userInfo == null ||
                !StringUtils.hasLength(userInfo.getUsername()) ||
                !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }

        int ret = userService.addUser(userInfo);
        System.out.println("adduser 受影响行数 " + ret);
//        int num = 10 / 0;  发生异常 数据就不会存到 数据库中了
//        如果 没发生异常 正常运行 那么数据就会保存在数据库中
        return ret;
    }





    @Autowired
    private LogInfoService logInfoService;

    @RequestMapping("/adduser4")
    // 事务的传播级别 默认是REQUIRED
    // 意思是 如果当前方法my事务 新建一个事务 如果已存在一个事务 那就加入该事务
    @Transactional(propagation = Propagation.REQUIRED)

//    事务1(实现事务的嵌套)  其他两个在LogInfoService中和UserService中
    public int addUser4(UserInfo userInfo) {
        // 运行之前 我们要判断传入的参数是否为空 如果为空 会导致sql拼接错误
        if (userInfo == null ||
                !StringUtils.hasLength(userInfo.getUsername()) ||
                !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }

        // 调用用户部分
        int userResult = userService.addUser2(userInfo);
        System.out.println("添加用户" + userResult + "条");


        // 调用日志事务部分
        int logResult = 0;
        LogInfo logInfo = new LogInfo();
        logInfo.setName("添加日志");
        logInfo.setDesc("添加日志的结果： " + logResult);
        logInfoService.addLog(logInfo);
        return userResult;
    }
    // 如果事物2 或者事务3  其中一个发生异常 那么事务2和事务3都会发生回滚











    @RequestMapping("/adduser5")
    // 不管你现在有没有事务 我们都需要创建一个事务
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int addUser5(UserInfo userInfo) {
        // 运行之前 我们要判断传入的参数是否为空 如果为空 会导致sql拼接错误
        if (userInfo == null ||
                !StringUtils.hasLength(userInfo.getUsername()) ||
                !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }

        // 调用用户部分
        int userResult = userService.addUser5(userInfo);
        System.out.println("添加用户" + userResult + "条");


        // 调用日志事务部分
        int logResult = 0;
        LogInfo logInfo = new LogInfo();
        logInfo.setName("添加日志");
        logInfo.setDesc("添加日志的结果： " + logResult);
        logInfoService.addLog5(logInfo);
        return userResult;
    }
    // 因为我们改变了 事务传播级别
    // 该级别 三个事务各自做自己的事 互相不影响 当事务3(保存日志)发生算数异常 那么就该保存日志回滚 而事务2的保存用户不会发生回滚


//    @Transactional(propagation = Propagation.NOT_SUPPORTED)
//    该事务级别是头铁 代码执行到哪 任务就完成到哪 不会存在回滚现象

//    @Transactional(propagation = Propagation.NESTED)支持嵌套

}
